來到了第 8 天。但一樣先講結論,如果你很急著用,可以直接使用這份 Add-On: Calendar to Sheet。如果想要自己試試看,那可以持續閱讀。對於想知道怎麼做的人,讓我們開始吧!
答案會在今天的文章中!
我們已經介紹了如何用 GAS 達到 (Google Form ->) Google Sheet -> Google Calendar 的流程。但如果今天我是想要反過來將 Google Calendar 上面的事件列出到 Google Sheet 呢? Google Calendar 內建的匯出是弄成 ICS 檔案。有沒有更簡單的方式可以直接在 Google Sheet 上面看到?這就是我們今天的主題。
那我們就開始吧!
因為我們要用到 Google Sheet ,所以一樣用其作為開啟的管道。
一樣執行時會有「需要驗證」出現,讓我借用一下 D2 的影片。
這邊我們沿用昨天的兩份行事曆,待會會主要抓 meeting_room_A
,也就是灰色的部分。
備註:這邊只做了四個在同一天的 mock events,但基本上可以抓出全部的事件。
如果是自己做,可以在建玩行事曆後,在「設定」這邊取得日曆的 ID。
接著,將兩個 ID 輸入到 GAS 的 environment.gs
當中。
這邊都跟昨天差不多。
Calendar.Events.list(cal_ID)
抓出所有的 Calendar Event!先用方式一,但因為這個 API 是舊版本的服務(v3),所以要多做點操作。但因為會列出所有的 Events,所以還是先介紹它。首先開立個 Calendar Service,在右手邊的服務中取得。
搞定 v3 的 Calendar API 後,就可以直接用其服務了抓到所有的 Calendar 物件了!
其 Object 大致上長這樣,我們待會再來看怎麼將其寫入 Google Sheet 當中。
讀出來的 Events 會依照創造的時間點排列,個人是建議可以先全部抓下來後再用 Google Sheet 進行排序 Sort。但實際使用上,我們會想知道一段時間的內事件,要怎麼進行有時間的搜索?這就到我們的 Q2 讀取特定 Google Calendar 事件。
前兩步 Step 1 / Step 2 都跟 Q1 一樣。
getEvents()
來取得特定時間內的行事曆很簡單,基本上就是用 getEvents(startTime, endTime)
來取得資料。要記得輸入的 Time 都要是 Date Object。這邊來示範一次怎麼抓。
function getCalendarEvents(){
let cal = CalendarApp.getCalendarById(room_A_ID);
var date = new Date();
var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
var events = cal.getEvents(firstDay, lastDay);
Logger.log(events);
Logger.log(events.length);
}
實際跑起來的樣子——
好,那接下來要怎麼「讀事件」呢?這就會回到我們最開始的小測驗。答案如下圖...。
至於 for...in
不行,有一個可能是因為 Calendar Array 不是 enumerable(出處),但詳細仍需要細節的研究。而答案寫成程式碼會變成這樣——
function getCalendarEvents(){
let cal = CalendarApp.getCalendarById(room_A_ID);
var date = new Date();
var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
var events = cal.getEvents(firstDay, lastDay);
for(let event of events){
Logger.log(event.getStartTime())
}
for (let i=0; i< events.length;i++){
Logger.log(events[i].getEndTime())
}
}
好,那實際讀起來長什麼樣子,在這邊我兩個方式都示範;用方式一讀開始時間,用方式二讀結束時間。
其他功能,則可以參考其他每一個 Object 還可以用的 Methods: Calendar Event。如果想搜尋特定名稱的事件,可以考慮加上 options
。另外對於「整日事件」,則有另外的抓法可以參考—— getEventsForDay(date, options)。
個人使用心得,雖然 Q1 是使用比較舊版的 API,但實際上它在抓資料時比較不囉唆,不會要限定時間和全天或時段事件。
Step 1 / 2 / 3 在 Q1 / Q2 都已經陳述過,這邊就專注在讀出來的資料要怎麼寫入。
這邊的邏輯是要「取範圍」 -> 「輸入數值」,重點也會是這兩步驟的細節怎麼寫。
setValues()
輸入數值這邊用一個假的資料來做示範,今天也主要先示範如何輸入「矩形、正方形範圍」的資料。假設我要在 A2:B4 這個範圍內輸入輸入一個矩形——
Index | A | B | C |
---|---|---|---|
2 | a | b | c |
3 | d | e | f |
先來看看程式碼。
function writeDate(){
let data = [['a','b','c'],['d','e','f']];
let starting_row = 2;
let starting_col = 1;
let num_row = data.length;
let num_col = data[0].length;
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange(starting_row, starting_col,num_row,num_col);
range.setValues(data);
}
也來看看這段程式碼會跑出的結果。
再來我們來讀一下 Code。其中大部分跟讀資料差不多,因為都要先取得範圍,可以回去參考 D6。其中一個不同的是,會是從 Array in array 的結構中取得 numRows(要取多少列) 和 numColumns(要取多少行)。這標要清楚的是 Array 的基本架構,可以搭配 W3C: Array 一起閱讀。
另外一個與 D6 不同的是透過 setValuse()
,在使用時主要是要注意「範圍」要先給出來。也就是我要先知道我要貼多少行與列,這邊就用 .length
的方式取得,然後我們再將 data 改成外部輸入的變數。最後寫資料的程式碼改成這樣。
function writeData(data){
let starting_row = 2;
let starting_col = 1;
let num_row = data.length;
let num_col = data[0].length;
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange(starting_row,
starting_col,
num_row,
num_col);
range.setValues(data);
}
我們來將前面兩題串到第三題,我們先分別將 Q1 和 Q2 的 Code 寫成 Array in array 的格式。像是 Q1 的長這樣——
function getCalendarEventList(){
var options = {
maxResults: 100
};
let events = Calendar.Events.list(room_A_ID, options);
let writed_data =[];
for (let item of events.items){
writed_data.push([item.id,
item.summary,
item.start,
item.end]);
};
Logger.log(writed_data)
}
跑起來長這樣——
而 Q2 寫起來長這樣——
function getCalendarEvents(){
let cal = CalendarApp.getCalendarById(room_A_ID);
let date = new Date();
let firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
let lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
let events = cal.getEvents(firstDay, lastDay);
let writed_data = []
for(let event of events){
writed_data.push([event.getTitle(),
event.getId(),
event.getStartTime(),
event.getEndTime()])
}
Logger.log(writed_data)
}
跑起來長這樣——
那最後就只要把 Logger.log(writed_data)
換成 writeData(writed_data)
就可以寫入資料庫了。
最後跑起來長這樣——
Google Advanced Calendar Service
Google Developer: Record time and activities in Calendar and Sheets
好,那我們就完成了。今天的份量比較多,主要學了...
Calendar.Events.list(cal_ID)
抓出所有的 Calendar EventgetEvents()
來取得特定時間內的行事曆事件setValues()
輸入數值字數也來到了七千多(但這次貼的程式碼比較多),總之,希望能有所幫助。今天比較值得一提的是, Read Google Calendar Events 並沒有特別提到 Quota 限制,雖然相信還是會有,所以大家使用上仍是要多加留意。好,那今天就是我們的 D8,明天 D9 會來講講怎麼列出 Google Drive 裡面所有檔案 ID 與設定複雜權限。如果還有問題,透過留言之外,也可以到 Facebook Group,想開很久這次鐵人賽才真的開起來哈哈哈,歡迎來當 Founding Member。如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。